home *** CD-ROM | disk | FTP | other *** search
- /*
- File: BitmapPrimitives.c
-
- Contains: QuickDraw GX to PostScript conversion code.
- File contains routines to translate Bitmap shapes
- into PostScript.
-
- Version: Technology: Quickdraw GX 1.1.x
-
- Copyright: © 1991-1997 by Apple Computer, Inc., all rights reserved.
- */
-
- #include "GXToPSBuildConfig.h"
- #include <GXGraphics.h>
- #include "GXGraphicsPriv.h"
- #include <GXEnvironment.h>
- #include "GXToPostScript.h"
- #include "IOUtilities.h"
- #include "RDUtil.h"
- #include "FontHandler.h"
- #include "PublicPostScriptIE.h"
- #include "private.h"
- #include "PSIEResources.h"
- #include "GXErrors.h"
- #include <OffscreenLibrary.h>
- #include "ShapeUtilities.h"
- #include <String.h>
- #include <Memory.h>
-
- #ifdef resumeLabel
- #undef resumeLabel
- #endif
- #define resumeLabel(exception)
-
- /*********************************************
-
- Function: CountPSDeviceSpaceComponents:
-
- Function returns the number of color components in a color space.
- Will return zero for illegal PostScript device spaces.
-
- **********************************************/
- long CountPSDeviceSpaceComponents(gxColorSpace theSpace);
- long CountPSDeviceSpaceComponents(gxColorSpace theSpace)
- {
- long nComponents;
-
- switch (theSpace) {
-
- case gxRGBSpace:
- nComponents = 3;
- break;
-
- case gxGraySpace:
- nComponents = 1;
- break;
-
- case gxCMYKSpace:
- nComponents = 4;
- break;
-
- default:
- nComponents = 0; // Has to be one of the other three.
- break;
-
- }//end switch
-
- return(nComponents);
-
- }//CountPSDeviceSpaceComponents
-
- //<FF>
- /************************************************
-
- Routine: MatchColorSetValues
-
- Routine matches an array of set colors in place:
-
- nColors: # of colors in array
- theSetColors: Array of set colors.
- setSpace: Color space of color set.
- setProfile: Color profile of color set.
- spaceToUse: Color space to convert to.
- profileToUse: Color profile to convert to.
- ************************************************/
- void MatchColorSetValues(long nColors, gxSetColor *theSetColors, gxColorSpace setSpace, gxColorProfile setProfile, gxColorSpace spaceToUse, gxColorProfile profileToUse);
- void MatchColorSetValues(long nColors, gxSetColor *theSetColors, gxColorSpace setSpace, gxColorProfile setProfile, gxColorSpace spaceToUse, gxColorProfile profileToUse)
- {
- gxSetColor* pSet;
- long i;
- gxColor tableEntry;
-
- pSet = theSetColors;
- for (i = nColors - 1; i >= 0; --i) {
-
- tableEntry.space = setSpace;
- tableEntry.profile = setProfile;
-
- // Move the component data into a color record for conversion.
- memcpy(&(tableEntry.element.component[0]), pSet, 4 * sizeof(gxColorValue) );
-
- GXConvertColor(&tableEntry, spaceToUse, nil, profileToUse);
-
- // Move it back.
- BlockMove((Ptr)&(tableEntry.element.component[0]), (Ptr)pSet, 4 * sizeof(gxColorValue));
-
- ++pSet;
-
- }//end for
-
- }//MatchColorSetValues
-
-
- //<FF>
- /************************************************
-
- Routine: OutputComponentArrays:
-
- Routine outputs the component arrays for a color set
- onto the postscript operand stack.
-
- pRDParams: pointer to the RD parameter block.
- nColors: number of colors in the color set.
- theSetColors: Array of setColors
- nComponents: Number of components in color space.
- level2Color: output for level2 color?
- whatSpace: what color space is this set?
-
- ************************************************/
- OSErr OutputComponentArrays( TRDParams *pRDParams, long nColors, gxSetColor *theSetColors, long nComponents, Boolean level2Color, gxColorSpace whatSpace);
- OSErr OutputComponentArrays( TRDParams *pRDParams, long nColors, gxSetColor *theSetColors, long nComponents, Boolean level2Color, gxColorSpace whatSpace)
- {
- OSErr status = noErr;
- long i, j;
- Ptr pComp;
-
- for (i = 0; i < nComponents; i++) {
-
- pRDParams->resIndex = kNewArray; // Create an array, leave it and 0 on operand stack.
- status = RDResPrintf(pRDParams, nColors); // Array has one entry for each color.
- nrequire(status, failed_Output);
-
- pComp =(Ptr)(&(theSetColors[0].component[i]));
-
- /**
- Prior to 1.2 we used to do this: For level-2 colors, output the short, otherwise output it as a fixed,
- now we always output a fixed, but we need to handle XYZ in a special case because the normalization is different.
- **/
-
- pRDParams->resIndex = kPutFixed;
-
- for (j = 0; j < nColors; j++) {
-
- if (whatSpace != gxXYZSpace)
- status = RDResPrintf(pRDParams, COMPONENTtoFIXED(*(unsigned short*)pComp) );
- else
- status = RDResPrintf(pRDParams, XYZCOMPONENTtoFIXED(*(unsigned short*)pComp) );
-
- nrequire(status, failed_Output);
-
- pComp += sizeof(gxSetColor);
-
- }//end for
-
- pRDParams->resIndex = kDoPop;
- nrequire( status = RDResPrintf(pRDParams), failed_Output); // pop last copy of index off stack.
-
- }//end for
-
- failed_Output:
- return(status);
-
- }//OutputComponentArrays
-
- //<FF>
- /************************************************
-
- ColorSetPrimitive
-
- Routine creates an indexed color space dictionary
- for the Graphics state. The dictionary for the colorSet
- dictionary is left on the operand stack.
-
- hIEGlobals: Imaging Engine globals handle
- theSet: The color set to output.
- theProfile: The color profile associated with whatever the colorSet was associated with
- since colorSets have no meaning on their own.
-
- **************************************************/
- OSErr ColorSetPrimitive(TIEGlobalsHdl hIEGlobals, gxColorSet theSet, gxColorProfile theProfile)
- {
- OSErr status;
- TIEGlobalsPtr pGlobals;
- TRDParams* pRDParams;
- gxColorSpace spaceToUse; // Color space to use for printer
- gxColorProfile profileToUse; // Profile to use for the printer
- short nColors; // Number of colors
- gxColorSpace setSpace; // Color space of the color set.
- gxSetColor *theSetColors; // Array of set colors from the color set.
- long nComponents; // Number of components in the color space to use.
- Boolean level2Color; // Are we doing level-2 color?
- Boolean useDeviceSpace; // Are we doing printer device space (no matching)?
-
- pGlobals = *hIEGlobals;
- pRDParams = pGlobals->pRDParams;
-
-
- /*** Allocate temporary storage for the colors ***/
-
- nColors = GXGetColorSet(theSet, nil, nil);
- require(nColors <= 256, failed_ColorSpace);
- nrequire(status = GXGetGraphicsError(nil), failed_ColorSpace);
-
- status = PSSetWorkSpaceSize(hIEGlobals, nColors * sizeof(gxSetColor));
- nrequire(status, failed_GetWrkSpace);
-
- HLockHi((*hIEGlobals)->hWorkSpace);
-
- theSetColors = (gxSetColor*)(*((*hIEGlobals)->hWorkSpace));
-
- /*** Get the colors ***/
-
- GXGetColorSet(theSet, &setSpace, theSetColors);
-
- /** Figure out how color space to translate to and how many components **/
-
- if ((*hIEGlobals)->params.renderOptions & gxUseLevel2ColorOption) {
-
- status = GetLevel2ColorSpace(setSpace, theProfile, &spaceToUse, &nComponents, &useDeviceSpace);
- nrequire(status, failed_ColorSpace);
- profileToUse = theProfile;
- level2Color = true;
-
- } else {
-
- spaceToUse = (*hIEGlobals)->params.devCSpace;
- profileToUse = pGlobals->params.devCProfile;
- level2Color = false;
- nComponents = CountPSDeviceSpaceComponents(spaceToUse);
- require(nComponents, failed_InvalidShapeSpace);
-
- }//end if
-
-
- /*** Color match all of the values ***/
-
- MatchColorSetValues(nColors, theSetColors, setSpace, theProfile, spaceToUse, profileToUse);
-
-
- /**** Create a PostScript array for each component ****/
-
- status = OutputComponentArrays(pRDParams, nColors, theSetColors, nComponents, level2Color, spaceToUse);
- nrequire(status, failed_components);
-
- /** If necessary put a color space on the stack, else put nil **/
-
- if (level2Color && !useDeviceSpace) {
-
- if (profileToUse == nil)
- profileToUse = (*hIEGlobals)->defaultProfileCopy;
-
- status = ColorSpacePrimitive(hIEGlobals, spaceToUse, profileToUse, false, nil);
- nrequire(status, failed_Output);
-
- } else {
-
- status = DoNull(pRDParams);
- nrequire(status, failed_Output);
-
- }//end if
-
-
- /** Now create a PostScript indexed color space with the arrays on the operand stack **/
-
- pRDParams->resIndex = kMakeColorSet;
- status = RDResPrintf(pRDParams, nComponents);
- ncheck(status);
-
- failed_components:
- failed_Output:
- failed_InvalidShapeSpace:
- failed_GetColors:
-
- /** Release the workspace, we're done with it **/
- {
- register OSErr saveStatus = PSReleaseWorkSpace(hIEGlobals);
- ncheck(saveStatus);
- if (status == noErr)
- status = saveStatus;
-
- }
-
- failed_GetWrkSpace:
- failed_ColorSpace:
-
- return(status);
-
- }//ColorSetPrimitive
-
-
-
-
-
- //<FF>
- /*** Macro converts the long at srcePtr to 12 bit A, B, C (in low 12 bits), increments pointer ***/
-
- #define GetNext12BitComponents(srcePtr, A, B, C) { \
- \
- /* Get the 10 bit components of first of two source pixels*/ \
- \
- C = *srcePtr++; \
- B = (C >> 10) & 0x000003FF; \
- A = (C >> 20) & 0x000003FF; \
- C &= 0x000003FF; \
- \
- /** Convert them to 12 bits per component by replicating high two bits **/ \
- \
- A = (A << 2) | ((A >> 8) & 0x00000003); \
- B = (B << 2) | ((B >> 8) & 0x00000003); \
- C = (C << 2) | ((C >> 8) & 0x00000003); \
- }
-
-
-
- /****************************************************
-
- Convert32to36:
-
- Function converts a 32 bit per pixel (10 bits per component) raster
- to a 12 bit per component (36 bits per pixel) raster.
-
- srceRaster: pointer to the source raster to convert.
- destRaster: pointer to a 36 bit per pixel raster to write into.
- width: width of the raster.
-
-
- Conversion will be as follows:
- 3 sets of two pixels at a time.
- That is 20 bits of source becomes 24 bits of destination.
-
- 1 interation:
- A,B ---> bytes 0 to 2
- C,A ---> bytes 3 to 5
- B,C ---> bytes 6 to 8
-
- ******************************************************/
- void Convert32to36(unsigned long *srceRaster, Ptr destRaster, long width);
- void Convert32to36(unsigned long *srceRaster, Ptr destRaster, long width)
- {
- unsigned long *srcePtr;
- unsigned char *dstPtr;
- long iterations;
- long i;
- register unsigned long A, B, C;
-
-
- srcePtr = srceRaster;
- dstPtr = (unsigned char*)destRaster;
-
- iterations = width / 2;
-
- for (i = 0; i < iterations; ++i) {
-
- GetNext12BitComponents(srcePtr, A, B, C);
-
- /* Byte 0 of destination is high 8 bits of A */
- *dstPtr++ = (A >> 4);
-
- /* Byte 1 of destination is low 4 bits of A plus high 4 bits of B */
- *dstPtr++ = ((A & 0x0000000F) << 4) | (B >> 8);
-
- /* Byte 2 of destination is low 8 bits of B */
- *dstPtr++ = (B & 0x000000FF);
-
- /* Byte 3 of destination is high 8 bits of C */
- *dstPtr++ = (C >> 4);
-
- /* Fill high 4 bits of byte 4 of destination with low 4 bits of C, don't increment dest yet. */
- *dstPtr = (C & 0x0000000F) << 4;
-
-
- /** Get second pixel in iteration pair **/
-
- GetNext12BitComponents(srcePtr, A, B, C);
-
- /* Fill low 4 bits of byte 4 of destination with high 4 bits of A */
- *dstPtr++ |= (A >> 8);
-
- /* Byte 5 of destination is low 8 bits of A */
- *dstPtr++ = (A & 0x000000FF);
-
- /* Byte 6 of destination is high 8 bits of B */
- *dstPtr++ = (B >> 4);
-
- /* Byte 7 of destination is low 4 bits of B plus high 4 bits of C */
- *dstPtr++ = ((B & 0x0000000F) << 4) | (C >> 8);
-
- /* Byte 8 of destination is low 8 bits of C */
- *dstPtr++ = (C & 0x000000FF);
-
- }//end for
-
- /** Handle the last odd pixel, same code as first half of above loop **/
-
- if (2 * iterations < width) {
-
- GetNext12BitComponents(srcePtr, A, B, C);
-
- /* Byte 0 of destination is high 8 bits of A */
- *dstPtr++ = (A >> 4);
-
- /* Byte 1 of destination is low 4 bits of A plus high 4 bits of B */
- *dstPtr++ = ((A & 0x0000000F) << 4) | (B >> 8);
-
- /* Byte 2 of destination is low 8 bits of B */
- *dstPtr++ = (B & 0x000000FF);
-
- /* Byte 3 of destination is high 8 bits ox C */
- *dstPtr++ = (C >> 4);
-
- /* Fill high 4 bits of byte 4 of destination with low 4 bits of C */
- *dstPtr = (C & 0x0000000F) << 4;
-
- }//end if
-
-
- }//Convert32to36
-
-
-
- //<FF>
- /****************************************************
-
- OutputABC12Data:
-
- Routine takes the 30 bits of XYZ/LAB/LUV from each 32 bit xyz32, lab32, luv32,
- converts them to 36 bits (12 per component) and buffers them.
-
- theBitmap: Pointer to the bitmap record.
- bandHeight: number of rasters.
- psRowBytes: what PostScript thinks the rowbytes should be.
-
- ******************************************************/
- OSErr OutputABC12Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes);
- OSErr OutputABC12Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes)
- {
- register long i;
- OSErr status;
- Ptr p36; // Pointer to our 36 bit buffer.
- Ptr pRaster; // Pointer to next offscreen raster.
- long flags;
-
- flags = gxNoBufferOptions;
- if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
- flags = gxMakeBufferHex;
-
-
- /*****
- The buffer for the 24 bit data is at the end of the workspace allocated for the
- offscreen bitmap
- *****/
- p36 = theBitmap->image + theBitmap->height * theBitmap->rowBytes;
-
- pRaster = theBitmap->image;
- for (i = bandHeight - 1; i >= 0; --i) {
-
- Convert32to36((unsigned long*)pRaster, p36, theBitmap->width);
-
- status = (*hIEGlobals)->psDevice->BufferData(p36, psRowBytes, flags);
- nrequire(status, failed_Raster);
-
- pRaster += theBitmap->rowBytes;
-
- }//end for
-
- failed_Raster:
-
- return(status);
-
- }//OutputABC12Data
-
-
-
- //<FF>
- /****************************************************
-
- OutputRGB32Data:
-
- Routine takes the 24 bits of RGB from each 32 bit rgb32Color
- and buffers them.
-
- theBitmap: Pointer to the bitmap record.
- bandHeight: number of rasters.
- psRowBytes: what PostScript thinks the rowbytes should be.
-
- ******************************************************/
- OSErr OutputRGB32Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes);
- OSErr OutputRGB32Data(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes)
- {
- register long i, j;
- OSErr status;
- Ptr p24; // Pointer to our 24 bit buffer.
- Ptr pRaster; // Pointer to next offscreen raster.
- Ptr pSrce, pDest;
- long flags;
-
- flags = gxNoBufferOptions;
- if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
- flags = gxMakeBufferHex;
-
-
- /*****
- The buffer for the 24 bit data is at the end of the workspace allocated for the
- offscreen bitmap
- *****/
- p24 = theBitmap->image + theBitmap->height * theBitmap->rowBytes;
-
- pRaster = theBitmap->image;
- for (i = bandHeight - 1; i >= 0; --i) {
-
- pSrce = pRaster;
- pDest = p24;
-
- for (j = theBitmap->width - 1; j >= 0; --j) {
-
- ++pSrce; // Skip the unused byte.
- *pDest++ = *pSrce++; //get red
- *pDest++ = *pSrce++; //get blue
- *pDest++ = *pSrce++; //get green
-
- }//end for
-
- status = (*hIEGlobals)->psDevice->BufferData(p24, psRowBytes, flags);
- nrequire(status, failed_Raster);
-
- pRaster += theBitmap->rowBytes;
-
- }//end for
-
- failed_Raster:
-
- return(status);
-
- }//OutputRGB32Data
-
-
-
- //<FF>
- /****************************************************
-
- OutputDirectData:
-
- Routine buffers data from a bitmap.
- This will not work for rgb, however. Because we must output
- the triplets without the 4th byte.
-
- theBitmap: pointer to the bitmap record.
- bandHeight: Number of rasters to output.
- psRowBytes: what PostScript thinks the rowbytes should be.
-
- *****************************************************/
- OSErr OutputDirectData(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes);
- OSErr OutputDirectData(TIEGlobalsHdl hIEGlobals, gxBitmap* theBitmap, long bandHeight, long psRowBytes)
- {
- register short i;
- OSErr status;
- register Ptr pRaster;
- long flags;
-
- flags = gxNoBufferOptions;
- if ((*hIEGlobals)->params.renderOptions & gxNeedsHexOption)
- flags = gxMakeBufferHex;
-
- pRaster = theBitmap->image;
- for (i = bandHeight - 1; i >= 0; --i) {
-
- status = (*hIEGlobals)->psDevice->BufferData(pRaster, psRowBytes, flags);
- nrequire(status, failed_Raster);
-
- #if DEBUGLEVEL > 0
- if (flags == gxMakeBufferHex) {
-
- char carriageReturn[] = "\n\r";
- status = (*hIEGlobals)->psDevice->BufferData(carriageReturn, 2, gxNoBufferOptions);
- nrequire(status, failed_Raster);
-
- }//end if
- #endif
-
- pRaster += theBitmap->rowBytes;
-
- }//end for
-
- failed_Raster:
-
- return(status);
-
- }//OutputDirectData
-
-
- //<FF>
- /***************************************************
-
- BandBitmap:
-
- Routine bands the source bitmap shape Into
- a bitmap in the image color space specified by
- the client.
-
- theShape: The source bitmap shape.
- offScreenBits: a bitmap record with space, profile, pixelSize and set initialized.
- psRowBytes: #bytes per raster that PostScript is expecting.
-
- *****************************************************/
- #define kBandSize 50
- OSErr BandBitmap(TIEGlobalsHdl hIEGlobals, gxShape theShape, gxBitmap *offScreenBits, long psRowBytes);
- OSErr BandBitmap(TIEGlobalsHdl hIEGlobals, gxShape theShape, gxBitmap *offScreenBits, long psRowBytes)
- {
- OSErr status;
- offscreen theBand; // Offscreen for banding into.
- gxTransform oldTransform, tempTransform;
- gxInk oldInk, tempInk;
- gxShape offScreenBitShape; // Shape for offscreen bitmap.
- gxBitmap srceBits; // Bitmap record of the source shape.
- long theSize;
- long bandY, bandHeight;
- gxPoint srceLocation, zeroZero;
- long rowLongs, rowBytes;
- gxShapeAttribute oldAttributes;
- gxShape specialShape = nil; // If the bitmap is a "special" bitmap from the transfer mode machine.
- gxShape eraser = nil; // We must erase the offscreen in white each time when doing "special" bitmap.
-
- zeroZero.x = 0; zeroZero.y = 0;
-
- oldAttributes = GXGetShapeAttributes(theShape);
- GXSetShapeAttributes(theShape, oldAttributes & ~gxMapTransformShape); // so MoveShapeTo moves position, not transform
-
- GXGetBitmap(theShape, &srceBits, &srceLocation); // Get the bitmap record of the shape.
-
- /**
- See if the bitmap is "special" bitmap generated by the RenderTransferMode machine.
- **/
- if (srceBits.rowBytes == -sizeof(gxShape)) { // rowbytes -4 signals "special bitmap"
- gxColor whiteColor;
- specialShape = (gxShape)(srceBits.image);
- eraser = GXNewShape(gxFullType);
- whiteColor.profile = srceBits.profile;
- whiteColor.space = gxGraySpace;
- whiteColor.element.gray = 0xFFFF;
- GXSetShapeColor(eraser, &whiteColor);
- }//end if
-
-
- /** Set up the offscreen bitmap **/
-
- offScreenBits->width = srceBits.width;
- offScreenBits->height = srceBits.height > kBandSize ? kBandSize : srceBits.height; //MIN( srceBits.height, kBandSize );
-
- rowBytes = (offScreenBits->width * offScreenBits->pixelSize) / 8;
- rowLongs = rowBytes / 4;
- if ((4 * rowLongs) < rowBytes);
- ++rowLongs;
-
- offScreenBits->rowBytes = 4 * rowLongs;
-
-
- /** Allocate space for the offscreen bitmap. **/
-
- theSize = offScreenBits->rowBytes * offScreenBits->height;
-
- /********
- RGB32 and the XYZ spaces require an additional buffer to hold 24 or 36 bit triplets
- because the raw data in the bitmap will be have an unused byte
- at the beginning. So OutputRGB32Data will use this extra buffer
- to create the 24 bit data and OutputABC12Data will use it for the 36 bit data.
- ********/
- if ((offScreenBits->space == gxRGB32Space) ||
- (offScreenBits->space == gxXYZ32Space) ||
- (offScreenBits->space == gxLAB32Space) ||
- (offScreenBits->space == gxLUV32Space) )
- theSize += psRowBytes;
-
- status = PSSetWorkSpaceSize(hIEGlobals, theSize);
- nrequire(status, failed_GetSpace);
-
- HLockHi((*hIEGlobals)->hWorkSpace);
-
- /** Create the offscreen **/
-
- offScreenBits->image = *((*hIEGlobals)->hWorkSpace);
-
- offScreenBitShape = GXNewBitmap(offScreenBits, &zeroZero); // Same location as source so pixels line up.
- status = GXGetGraphicsError(nil);
- nrequire(status, failed_CreateBitmap);
-
-
- /*****
- Do a GetBitmap because NewBitmap may have updated some fields in the bitmap structure.
- such as colorSpace and colorSet
- *****/
-
- GXGetBitmap(offScreenBitShape, offScreenBits, nil);
-
- CreateOffscreen(&theBand, offScreenBitShape);
- nrequire(status = GXGetGraphicsError(nil), failed_CreateOffscreen);
-
- /* Make sure matching is enabled for the port */
-
- GXSetViewPortAttributes(theBand.port, GXGetViewPortAttributes(theBand.port) | gxEnableMatchPort);
-
-
- /*******************************
-
- Now band the bitmap
-
- ********************************/
- /*******
- Give the shape an identity trasnform (which we will move to accomplish banding):
- we don't want it transformed while we band into offscreen.
- The new transform's viewport will be the offscreen's viewport.
-
- *******/
-
- oldTransform = GXCloneTransform(GXGetShapeTransform(theShape));
- tempTransform = GXNewTransform();
- GXSetTransformViewPorts(tempTransform, 1, &(theBand.port));
- GXSetShapeTransform(theShape, tempTransform);
- GXMoveShapeTo(theShape, 0, 0); // Line it up with offscreen.
-
- /* If we are drawing the "special" bitmap from the transfer mode engine, then set up for device space */
- if (specialShape != nil) {
- gxMapping deviceMapping;
- CopyToMapping(&deviceMapping, &(*hIEGlobals)->deviceMapping);
- MoveMapping(&deviceMapping, -srceLocation.x, -srceLocation.y);
- GXSetShapeViewPorts(specialShape, 1, &(theBand.port));
- GXSetShapeViewPorts(eraser, 1, &(theBand.port));
- GXSetViewPortMapping(theBand.port, &deviceMapping);
- }//end if
-
- /****
- Put a default ink on so it has copy transfer-mode.
- This should mean we don't have to earase the destination first.
- ****/
- oldInk = GXCloneInk(GXGetShapeInk(theShape));
- tempInk = GXNewInk();
- GXSetShapeInk(theShape, tempInk);
-
- /**
- Now loop to band out the image to the PostScript device.
- **/
- for (bandY = 0; bandY < srceBits.height; bandY += kBandSize) {
-
- bandHeight = kBandSize;
- if (bandY + bandHeight >= srceBits.height)
- bandHeight = srceBits.height - bandY;
-
- if (specialShape == nil) {
- GXDrawShape(theShape);
- GXMoveTransform(tempTransform, 0, -ff(kBandSize)); // move the shape for the next band.
- } else {
- gxMapping portMap;
- GXDrawShape(eraser);
- GXDrawShape(specialShape);
- /* Map the port, we do this here rather than moving the shape becuase of port alligned patterns, etc. */
- GXGetViewPortMapping(theBand.port, &portMap);
- MoveMapping(&portMap, 0, -ff(kBandSize));
- GXSetViewPortMapping(theBand.port, &portMap);
- }//end if
- status = GXGetGraphicsError(nil);
- nrequire(status, failed_Draw);
-
- /** Use monet to match the bitmap if necessary **/
-
- /** Output the data to PostScript **/
- switch(offScreenBits->space) {
-
- case gxIndexedSpace:
- case gxCMYK32Space:
- status = OutputDirectData(hIEGlobals, offScreenBits, bandHeight, psRowBytes);
- ncheck(status);
- break;
-
- case gxRGB32Space:
- status = OutputRGB32Data(hIEGlobals, offScreenBits, bandHeight, psRowBytes);
- ncheck(status);
- break;
-
- case gxXYZ32Space:
- case gxLAB32Space:
- case gxLUV32Space:
- status = OutputABC12Data(hIEGlobals, offScreenBits, bandHeight, psRowBytes);
- ncheck(status);
- break;
-
- default:
- #if DEBUGLEVEL > 0
- dprintf(notrace, "Image Color Space not implemented: %d", (long)(offScreenBits->space));
- #endif
- break;
-
- }//end switch
-
- nrequire(status, failed_Output);
-
- }//end for
-
-
- /** Output a carriage-return and new line just for file-clarity's sake after all bitmap data **/
-
- nrequire(status = (*hIEGlobals)->psDevice->BufferData("\r\n", 2, gxNoBufferOptions), failed_Output);
-
- failed_Draw:
-
-
- failed_Output:
-
- GXSetShapeTransform(theShape, oldTransform); // restore the bitmap's transform.
- GXSetShapeInk(theShape, oldInk); // restore the bitmap's ink.
- GXMoveShapeTo(theShape, srceLocation.x, srceLocation.y); // Put it back where it was.
- GXSetShapeAttributes(theShape, oldAttributes); // Restore the attributes
- GXDisposeInk(tempInk); // Clean up inks.
- GXDisposeInk(oldInk);
- GXDisposeTransform(tempTransform); // Clean up transforms.
- GXDisposeTransform(oldTransform);
- DisposeOffscreen(&theBand); // Clean up offscreen.
-
- failed_CreateOffscreen:
-
- GXDisposeShape(offScreenBitShape);
-
- failed_CreateBitmap:
-
- {
- OSErr saveStatus = PSReleaseWorkSpace(hIEGlobals);
- ncheck(saveStatus);
- if (status == noErr)
- status = saveStatus;
-
- }
-
- failed_GetSpace:
-
- return(status);
-
- }//BandBitmap
-
-
-
- //<FF>
- /*************************************
- Routine: SetupOffscreenBitmap.
-
- Routine sets up the offscreen bitmap to be
- used for banding the bitmap. The bitmap record
- returned will be used to set up an offscreen
- for banding
-
- theBits: pointer to the source bitmap record.
- offscreenBits: pointer a bitmap record for the offscreen
- cmpSize: bits/component to use for PostScript image operation.
- cmpCount: # of components.
- useLevel2: (Input/Output) (Input true means try to, output false means can't)
-
- ****************************************/
- void SetupOffscreenBitmap(TIEGlobalsHdl hIEGlobals, gxBitmap *theBits, gxBitmap *offscreenBits, long *cmpSize, long *cmpCount, Boolean *useLevel2);
- void SetupOffscreenBitmap(TIEGlobalsHdl hIEGlobals, gxBitmap *theBits, gxBitmap *offscreenBits, long *cmpSize, long *cmpCount, Boolean *useLevel2)
- {
- TIEGlobalsPtr pGlobals = *hIEGlobals;
- Boolean useIndexed = false; // should we use an indexed color space?
-
- if (theBits->space == gxIndexedSpace) {
-
- /** 1, 2 or 4 bit indexed should always be used. **/
-
- if ( theBits->pixelSize < 8 )
- useIndexed = true;
-
-
- /****
- For 8-bit, it only makes sense to use colorset if the device is not graySpace,
- or we are using level-2 color. The net result is that for 8 bit indexed,
- where the device is level-1 gray we just get an image operator. (Because
- the offscreen we will use will be the gray color set offscreen which
- is equivelent to the standard PostScript image operator.
- ****/
-
- if ( (theBits->pixelSize == 8) && ( (pGlobals->params.devCSpace != gxGraySpace) || *useLevel2 ) )
- useIndexed = true;
-
- }//end if
-
-
- /** Set up the fields of the offscreen **/
-
- if (useIndexed) {
-
- offscreenBits->set = theBits->set;
- offscreenBits->space = theBits->space;
- offscreenBits->profile = theBits->profile;
- offscreenBits->pixelSize = theBits->pixelSize;
- *cmpCount = 1;
- *cmpSize = theBits->pixelSize;
-
- } else {
-
- /*****
- For level-2 color option set up the offscreen to convert to a level-2
- supported space and profile.
- otherwise set up the offscreen to reflect the device's color space
- ******/
-
- if (*useLevel2) {
-
- long profileSize;
- Boolean useDeviceSpace = false; // Should we use postscript device color spaces ?
- /******
- If the profile is nil (though this should never be the case from an unflattened shape
- Make it the default profile copy so we can pass it through clone and dispose
- without headaches
- *******/
- if (theBits->profile == nil)
- theBits->profile = (*hIEGlobals)->defaultProfileCopy;
-
- /* Find out if we should do matching */
- profileSize = GetColorProfileSize(theBits->profile, nil);
- if (profileSize == 0)
- useDeviceSpace = true;
-
- offscreenBits->profile = theBits->profile;
- offscreenBits->pixelSize = 32;
- *cmpCount = 3;
-
- switch(theBits->space) {
-
- case gxCMYK32Space:
- if (useDeviceSpace) {
- offscreenBits->space = gxCMYK32Space;
- *cmpSize = 8;
- *cmpCount = 4;
- *useLevel2 = false; // Make BitmapPrimitive do normal colorimage.
- } else {
- /***
- For color Level2 matching, convert cmyk to xyz - there is no way to do cmyk
- in 3 component PostScript device independant spaces.
- ****/
- offscreenBits->space = gxXYZ32Space;
- *cmpSize = 12;
- *cmpCount = 3;
- }//end if
- break;
-
- case gxYXY32Space:
- case gxLUV32Space: // maybe able to support without conversion to XYZ
- case gxLAB32Space: // maybe able to support without conversion to XYZ
- case gxYIQ32Space: // maybe able to support without conversion to XYZ
- case gxXYZ32Space:
- offscreenBits->space = gxXYZ32Space;
- *cmpSize = 12;
- break;
-
- case gxRGB16Space:
- case gxHSV32Space:
- case gxHLS32Space:
- case gxARGB32Space:
- case gxRGB32Space:
- offscreenBits->space = gxRGB32Space;
- *cmpSize = 8;
- *useLevel2 = !useDeviceSpace; // Make BitmapPrimitive do normal colorimage for no-match profile.
- break;
-
- default:
- #if DEBUGLEVEL > 0
- dprintf(notrace, "Bug, Colorspace not implemented: %d", theBits->space);
- #endif
- break;
-
- }//end switch
-
- } else {
-
- /** Set up the offscreen for a standard level-1 image or colorimage operator **/
-
- offscreenBits->profile = pGlobals->params.devCProfile;
- switch(pGlobals->params.devCSpace) {
-
- case gxCMYKSpace:
- offscreenBits->pixelSize = 32;
- offscreenBits->space = gxCMYK32Space;
- *cmpSize = 8;
- *cmpCount = 4;
- break;
-
- case gxRGBSpace:
- offscreenBits->pixelSize = 32;
- offscreenBits->space = gxRGB32Space;
- *cmpSize = 8;
- *cmpCount = 3;
- break;
-
- case gxGraySpace:
- offscreenBits->pixelSize = 8;
- offscreenBits->space = gxIndexedSpace;
- offscreenBits->set = pGlobals->graySet;
- *cmpSize = 8;
- *cmpCount = 1;
- break;
-
- default:
- #if DEBUGLEVEL > 0
- dprintf(notrace, "Bug, Unsupported device color space: %d", pGlobals->params.devCSpace);
- #endif
- break;
-
- }//end switch
-
- }//end if
-
- }//end if
-
- }//SetupOffscreenBitmap
-
-
-
- //<FF>
- /***********************************************
-
- BitmapPrimitive:
-
- Routine controls the translation of all bitmap shapes
- into PostScript.
-
- Sets up the parts of the offscreen bitmap structure for rendering into:
- pixelSize, colorSpace, colorProfile, and colorSet. The rest will
- be set up by BandBitmap
-
- *************************************************/
- OSErr BitmapPrimitive(TIEGlobalsHdl hIEGlobals, gxShape theShape, TgeometryOptions geomOptions)
- {
- OSErr status;
- gxBitmap theBits; // the bitmap structure from the shape.
- gxBitmap offScreenBits; // Offscreen bitmap to render into.
- gxPoint location; // bitmaps location.
- long cmpSize; // color component size for PostScript
- long cmpCount; // Number of color components for PostScript.
- long psRowBytes; // Number of bytes per raster for PostScript.
- TIEGlobalsPtr pGlobals;
- TRDParams* pRDParams;
- Boolean doImageMask = false; // Can the bitmap be imagemasked?
- Boolean doIndexedColors = false; // Are we using an indexed color space?
- Boolean needsEOD = false; // Do we need to output an EOD character for L2 file filter?
- Boolean useLevel2 = false; // Are we using level-2 color?
- long needsHex; // true or false for outputting bitmap data as hex.
-
-
- pGlobals = *hIEGlobals;
- pRDParams = pGlobals->pRDParams;
-
- needsHex = pGlobals->params.renderOptions & gxNeedsHexOption ? true : false;
- useLevel2 = pGlobals->params.renderOptions & gxUseLevel2ColorOption ? true : false;
-
- GXGetBitmap(theShape, &theBits, &location); // Get the bitmap data structure.
- status = GXGetGraphicsError(nil);
- nrequire(status, failed_GetBitmap);
-
- /** Check to see if the bitmap has dimensions worth processing **/
- if (theBits.width > 0 && theBits.height > 0) {
-
- /** Figure out what the bits PS will need **/
- SetupOffscreenBitmap(hIEGlobals, &theBits, &offScreenBits, &cmpSize, &cmpCount, &useLevel2);
-
- /** Determine what postscript will be used based on the offscreen that was set up **/
-
- doIndexedColors = false;
- doImageMask = false;
- if (offScreenBits.space == gxIndexedSpace) {
-
- if (offScreenBits.set != pGlobals->graySet) { // graySet means use gray image operator.
-
- doIndexedColors = true; // any other set means use indexed.
- if (offScreenBits.pixelSize == 1)
- doImageMask = true;
-
- }//end if
-
- }//end if
-
- /** Calculate the number of bytes per raster that PostScript will expect **/
-
- psRowBytes = (theBits.width * cmpCount * cmpSize + 7) / 8;
-
- if (geomOptions & eMakeProcedure) {
-
- /************************************************
- The PostScript for a procedure will be:
- colorSet dictionary (for indexed)
- or a colorSpace array (level-2 direct color only)
- bitmapStrings
- bits/pixel
- geometry procedure
- *************************************************/
-
-
- /****
- Output the colorset dictionary
- ****/
- if (doIndexedColors) {
-
- status = ColorSetPrimitive(hIEGlobals, theBits.set, theBits.profile);
- nrequire(status, failed_DoBitmap);
-
- } else if (useLevel2) {
-
- status = ColorSpacePrimitive(hIEGlobals, offScreenBits.space, offScreenBits.profile, false, nil);
- nrequire(status, failed_DoBitmap);
-
- } else {
-
- status = DoNull(pRDParams);
- nrequire(status, failed_DoBitmap);
-
- }//end if
-
- /****
- Make the bitmap strings
- ****/
-
- /* output the header for making the strings */
- pRDParams->resIndex = kMakeBitStrings;
- status = RDResPrintf(pRDParams, needsHex, psRowBytes * theBits.height);
- nrequire(status, failed_DoBitmap);
-
- /*****
- Flush the RDResPrintf buffer and
- Output the image data
- *****/
- status = RDFlushBuffer((*hIEGlobals)->rdMap);
- nrequire(status, failed_rdFlush);
-
- /* Band the data to make the strings */
- status = BandBitmap(hIEGlobals, theShape, &offScreenBits, psRowBytes);
- nrequire(status, failed_DoBitmap);
-
- /****
- First put the bits per pixel on the stack for MakeShapeDict:
- ****/
-
- pRDParams->resIndex = kDoInt;
- nrequire(status = RDResPrintf(pRDParams, cmpSize), failed_DoBitmap);
-
- /****
- Make the geometry procedure
- ****/
-
- if (doImageMask) {
-
- pRDParams->resIndex = k1bitBitmapProc;
- status = RDResPrintf(pRDParams, theBits.width, theBits.height, &location);
-
- } else if (doIndexedColors) {
-
- pRDParams->resIndex = kIndexedBitProc;
- status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location);
-
- } else if (useLevel2) {
-
- pRDParams->resIndex = kL2BitmapProc;
- status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location);
-
- } else {
-
- pRDParams->resIndex = kBitmapProc;
- status = RDResPrintf(pRDParams, cmpCount, theBits.width, theBits.height, cmpSize, &location);
-
- }//end if
- nrequire(status, failed_DoBitmap);
-
-
- } else {
-
- /*************************************************
- The PostScript for drawing will be:
- setting the colorSet if necessary
- setting the colorspace if necessary (for level-2 color options)
- image header (parameters for DoBitmap or DoIndexedBitmap
- the data
- *************************************************/
-
- /****
- Set the colorSet if necessary
- ****/
- if (doIndexedColors &&
- ((pGlobals->ieStateFlags & eColorSetOutOfDate) ||
- !PSEqualColorSet(pGlobals->theColorSet, theBits.set)) ) {
-
- status = ColorSetPrimitive(hIEGlobals, theBits.set, theBits.profile);
- nrequire(status, failed_DoBitmap);
-
- pGlobals = *hIEGlobals; // ColorSetPrim could have moved memory.
- PSDisposeColorSet(pGlobals->theColorSet);
- pGlobals->theColorSet = GXCloneColorSet(theBits.set);
- pRDParams->resIndex = kSetColorSet;
- status = RDResPrintf(pRDParams);
- nrequire(status, failed_DoBitmap);
-
- pGlobals = *hIEGlobals; // resprintf could have moved memory.
- pGlobals->ieStateFlags &= ~eColorSetOutOfDate; // it is now current.
-
- }//end if
-
- /****
- Do the image header
- *****/
- if (doImageMask) {
-
- if (GXGetShapeTags(theShape, rasterizedShapeTag, 1, gxSelectToEnd, nil) ) { /** Is this some rasterized text with an additional matrix?? **/
-
- /** Bitmaps that are rasterizations of other shapes (kanji text) have additional mappings on them. **/
-
- gxMapping *additionalMapping;
- gxTag psrsTag;
-
- GXGetShapeTags(theShape, rasterizedShapeTag, 1, gxSelectToEnd, &psrsTag);
- GXLockTag(psrsTag);
- additionalMapping = (gxMapping*)GXGetTagStructure(psrsTag, nil);
-
- pRDParams->resIndex = k1bitBitmapPSRS;
- status = RDResPrintf(pRDParams, theBits.width, theBits.height, &location, needsHex, psRowBytes,
- additionalMapping->map[0][0], additionalMapping->map[0][1],
- additionalMapping->map[1][0], additionalMapping->map[1][1],
- additionalMapping->map[2][0], additionalMapping->map[2][1],
- additionalMapping->map[2][2]);
-
- GXUnlockTag(psrsTag);
-
- } else { /** Thank god! Just a normal bitmap **/
-
- pRDParams->resIndex = k1bitBitmap;
- status = RDResPrintf(pRDParams, theBits.width, theBits.height, &location,
- needsHex, psRowBytes);
-
- }//end if
-
- } else if (doIndexedColors) {
-
- pRDParams->resIndex = kIndexedImage;
- status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location,
- needsHex, psRowBytes);
-
- } else if (useLevel2) {
-
- /****
- Set the color space
- ****/
-
- status = ColorSpacePrimitive(hIEGlobals, offScreenBits.space, offScreenBits.profile, true, nil);
- nrequire(status, failed_DoBitmap);
-
- pRDParams->resIndex = kL2Image;
- status = RDResPrintf(pRDParams, theBits.width, theBits.height, cmpSize, &location, needsHex);
-
- /** Level 2 image uses dictionary which will use filter for hex, so we need EOD **/
- if (needsHex)
- needsEOD = true;
-
- } else {
-
- pRDParams->resIndex = kImage;
- status = RDResPrintf(pRDParams, cmpCount, theBits.width, theBits.height,
- cmpSize, &location, needsHex, psRowBytes);
-
- /* If we did a normal bitmap then that means if we are level-2 we are now in L2 device space */
- pGlobals = *hIEGlobals;
- pGlobals->gStateNest[pGlobals->gStateDepth].level2DevSpace = true; /* Now in Level-2 device space */
- pGlobals->gStateNest[pGlobals->gStateDepth].currSpace = theBits.space;
-
- }//end if
- nrequire(status, failed_DoBitmap);
-
- /*****
- Flush the RDResPrintf buffer and
- Output the image data
- *****/
- status = RDFlushBuffer((*hIEGlobals)->rdMap);
- nrequire(status, failed_rdFlush);
-
- status = BandBitmap(hIEGlobals, theShape, &offScreenBits, psRowBytes);
- nrequire(status, failed_DoBitmap);
-
- if (needsEOD) {
-
- /** The EOD for the hex filter is the ">" character **/
- nrequire(status = (*hIEGlobals)->psDevice->BufferData(">\r\n", 3, gxNoBufferOptions), failed_OutputEOD);
-
- }//end if
-
-
- }//end if
-
-
- }//end if
-
-
- failed_OutputEOD:
- failed_rdFlush:
- failed_DoBitmap:
-
- failed_GetColorSpace:
-
- failed_GetBitmap:
-
- return(status);
-
- }//BitmapPrimitive
-
-